#include <iostream>
#include "L2_cache.h"
#include "L1_data_cache.h"
#include "util.h"

/****************************************
    MESI Protocol
****************************************/

void performMESIForDataModified(unsigned int counter){
    
    string init_state, next_state;
    switch (counter % ModifyFreq) {
        case 0:
        case 5:
        case 9:
            init_state = "Shared";
            next_state = "Modified";
            // cout << "L2 | Modifying shared data. Invalidate Others\n";
            break;
        default:
            init_state = "Exclusive";
            next_state = "Modified";
            break;    
    }   
    //// cout << "L2 | Datum went from  " << init_state << " to " << next_state << endl;
}

/****************************************
    L2_cache Read/Write/Modify 
****************************************/

void L2_cache::readRequest(unsigned int addr, unsigned int* data){    
    unsigned int offset = L1_data_cache::getOffSet(addr);
    data[offset] = addr;        
    // cout << "L2 | Reading Data from Memory\n";
    
    readCounter++;
    // if(readCounter % InvalidateFreq == 0){
    //     addr = (unsigned int)getRandomNumber()*0xfffffff;
    //     data_cache->invalidate(addr);
    // }
}

void L2_cache::writeRequest(unsigned int addr, unsigned int data){
    // cout << "L2 | Recieved a write request\n";
}

void L2_cache::dataCacheModified(unsigned int addr){
    
    // cout << "L2 | Data Modified at " << L1_data_cache::getIndex(addr) << ":" << L1_data_cache::getOffSet(addr) << "(indx:offset)\n";
    
    modifiedCounter++;
    performMESIForDataModified(modifiedCounter);
    
}

void L2_cache::invalidateDataCache(unsigned int addr)
{
    // cout<<"L2 | Invalidating Data at " << L1_data_cache::getIndex(addr) << ":" << L1_data_cache::getOffSet(addr) << "(indx:offset)\n";
    data_cache->invalidate(addr);
}

L2_cache::L2_cache()
{
    modifiedCounter = 0;
    readCounter = 0;
    writeCounter = 0;    
}